// Linux API
#include <arpa/inet.h>
// C API
#include <assert.h>
#include <string.h>
// owner
#include "InetAddress.hpp"
#include "SocketsOps.hpp"

namespace tulun
{
    // InetAddress::
    // struct sockaddr_in addr_;
    static const int slen = 64;
    InetAddress::InetAddress()
        : addr_{}
    {
    }
    InetAddress::InetAddress(const std::string &ip, const short port)
        : addr_{}
    {
        addr_.sin_family = AF_INET;
        setIp(ip);
        setPort(port);
        // Sockets::fromIpPort(ip.c_str(), port, &addr_);
    }
    InetAddress::InetAddress(const struct sockaddr_in &addr)
        : addr_{addr}
    {
    }

    void InetAddress::setIp(const std::string &ip)
    {
        inet_pton(AF_INET, ip.c_str(), &addr_.sin_addr.s_addr);
    }
    void InetAddress::setPort(const short port)
    {
        addr_.sin_port = ::htons(port);
    }

    std::string InetAddress::toIp() const
    {
        char buf[slen] = {};
        inet_ntop(AF_INET, &addr_.sin_addr, buf, slen);
        return std::string(buf);
    }
    std::string InetAddress::toIpPort() const
    {
        char buf[slen] = {};
        inet_ntop(AF_INET, &addr_.sin_addr, buf, slen);
        int pos = strlen(buf);
        assert(pos < slen);
        uint16_t port = ntohs(addr_.sin_port);
        sprintf(buf + pos, ":%u", port);
        return std::string(buf);
    }
    std::uint16_t InetAddress::toPort() const
    {
        return ntohs(addr_.sin_port);
    }
    const struct sockaddr_in &InetAddress::getSockAddrInet() const
    {
        return addr_;
    }
    void InetAddress::setSockAddrInet(const struct sockaddr_in &addr)
    {
        addr_ = addr;
    }

    uint32_t InetAddress::ipNetEndian() const
    {
        return addr_.sin_addr.s_addr;
    }
    uint16_t InetAddress::portNetEndian() const
    {
        return addr_.sin_port;
    }

} // namespace tulun